Hands-on Exercise 03 - Animated Data Visualisations

Published

January 21, 2024

Modified

January 25, 2024

1. Overview

In the second part of the third lesson, we learn to create animated data visualisations using gganimate and plotly packages.

2. Getting Started

2.1. Installing and Loading Packages

We will use the following R packages in addition to tidyverse and plotly for this exercise:

  1. gganimate: ggplot2 extension to create animated statistical graphs

  2. gifski: creates GIF animations

  3. gapminder: an excerpt of the data availabe on gapminder.org. We will use it country_colors scheme.

The packages to be used can be installed and loaded into the R environment using the p_load() function from the pacman package.

pacman::p_load(tidyverse, plotly, 
               gganimate, gifski, gapminder)

2.2. Import Data

Next, we will read the data provided by the Course Instructor into the R environment. As the data is in .xls format, we will use the read_xls() function from the readxl package. We will call the function without loading the package into the environment:

global_pop <- readxl::read_xls("data/GlobalPopulation.xls",
                               sheet="Data")
glimpse(global_pop)
Rows: 6,204
Columns: 6
$ Country    <chr> "Afghanistan", "Afghanistan", "Afghanistan", "Afghanistan",…
$ Year       <dbl> 1996, 1998, 2000, 2002, 2004, 2006, 2008, 2010, 2012, 2014,…
$ Young      <dbl> 83.6, 84.1, 84.6, 85.1, 84.5, 84.3, 84.1, 83.7, 82.9, 82.1,…
$ Old        <dbl> 4.5, 4.5, 4.5, 4.5, 4.5, 4.6, 4.6, 4.6, 4.6, 4.7, 4.7, 4.7,…
$ Population <dbl> 21559.9, 22912.8, 23898.2, 25268.4, 28513.7, 31057.0, 32738…
$ Continent  <chr> "Asia", "Asia", "Asia", "Asia", "Asia", "Asia", "Asia", "As…

Using glimpse(), we can see that the records under Country and Continent are recorded as chr, while Year is recorded as dbl. We will use the following code to change Country and Continent to factor data type, and Year to integer data type.

col <- c("Country", "Continent")
global_pop <- global_pop %>%
  mutate_at(col, as.factor) %>%
  mutate(Year = as.integer(Year))

glimpse(global_pop)
Rows: 6,204
Columns: 6
$ Country    <fct> "Afghanistan", "Afghanistan", "Afghanistan", "Afghanistan",…
$ Year       <int> 1996, 1998, 2000, 2002, 2004, 2006, 2008, 2010, 2012, 2014,…
$ Young      <dbl> 83.6, 84.1, 84.6, 85.1, 84.5, 84.3, 84.1, 83.7, 82.9, 82.1,…
$ Old        <dbl> 4.5, 4.5, 4.5, 4.5, 4.5, 4.6, 4.6, 4.6, 4.6, 4.7, 4.7, 4.7,…
$ Population <dbl> 21559.9, 22912.8, 23898.2, 25268.4, 28513.7, 31057.0, 32738…
$ Continent  <fct> Asia, Asia, Asia, Asia, Asia, Asia, Asia, Asia, Asia, Asia,…

3. gganimate Methods to Create Animated Data Visualisation

gganimate provides additional grammar classes that can be added to the plot object to dictate how the plot should change in the animation:

  • transition_*(): defines how the data should be spread out and how it relates to itself over time

  • view_*(): defines how the positional sclaes should change throughout the animation

  • shadow_*(): defines how data from other time points should be presented in the given time point

  • enter_*() / exit_*(): defines how new data should appear and how old data should disappear during the animation

  • ease_aes(): defines hpw different aesthestics should be eased during transitions

In this example, we build an animated plot using transition_time() and ease_aes():

ggplot(data = global_pop,
       aes(x = Old,
           y = Young,
           size = Population,
           color = Country)) +
  geom_point(alpha = 0.7,
             show.legend = FALSE) +
  scale_color_manual(values = country_colors) +
  scale_size(range = c(2, 12)) +
  labs(title = 'Year: {frame_time}',
       x = '% Aged',
       y = '% Young')

ggplot(data = global_pop, 
       aes(x = Old, 
           y = Young,
           size = Population,
           colour = Country)) +
  geom_point(alpha = 0.7, 
             show.legend = FALSE) +
  scale_colour_manual(values = country_colors) +
  scale_size(range = c(2, 12)) +
  labs(title = 'Year: {frame_time}', 
       x = '% Aged', 
       y = '% Young') +
  transition_time(Year) +       
  ease_aes('linear')

Note
  • transition_time() is used to create transitions through distinct points in time (e.g. Year)

  • ease_aes() is used to control the easing of aesthetics. The default is linear, other methods include quadratic, cubic, quartic, quintic, sine, circular, exponential, elastic, back, and bounce.

4. plotly Methods to Create Animated Data Visualisation

In the plotly package, both plot_ly() and ggplotly() functions support key frame animations through the frame argument. The ids argument can be used to ensure smooth transitions between objects with the same id.

We explore both methods below:

plot <- global_pop %>%
  plot_ly(x = ~Old,
          y = ~Young,
          size = ~Population,
          color = ~Continent,
          sizes = c(2,100),
          frame = ~Year,
          text = ~Country,
          hoverinfo = "text",
          type = 'scatter',
          mode = 'markers'
          ) %>%
  layout(showlegend = FALSE)

plot
plot <- ggplot(data = global_pop,
       aes(x = Old,
           y = Young,
           size = Population,
           color = Country)) +
  geom_point(aes(size = Population,
                 frame = Year),
             alpha = 0.7) +
  scale_color_manual(values = country_colors) +
  scale_size(range = c(2, 12)) +
  labs(x = '% Aged',
       y = '% Young') +
  theme(legend.position = 'none')

ggplotly(plot)